import 'dart:convert';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:flutter_elf/utils/print_utils.dart';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_elf/_base/build_config.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'entity_factory.dart';
import 'api_code.dart';
export 'Api.dart';

final httpErrorTest = (e) => e is HttpError;
final resErrorTest = (e) => e is ResError;

///单例请求
class HttpManagers {
  Dio _dio;
  static final HttpManagers instance = HttpManagers._internal();


  factory HttpManagers() => instance;

  HttpManagers._internal() {
    initDio();
  }

  void initDio() {
    // 配置dio实例
    BaseOptions options = BaseOptions(
      connectTimeout: 15000,
      receiveTimeout: 15000,
      contentType: 'application/json',
    );
    //设置请求头
    options.headers = {"timeoutMs": 15000, "Authorization": null};
    _dio = new Dio(options);
    settingInterceptor();
  }

  //设置token
  void setToken(String token) => setHeader("Authorization", token);

  //设置header
  void setHeader(String key, value) => _dio?.options?.headers[key] = value;

  void settingInterceptor() {
    //证书
//    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
//        (client) {
//      client.badCertificateCallback =
//          (X509Certificate cert, String host, int port) => true;
////      if (BuildConfig.isDebug) {
////        client.findProxy = (uri) {
//////         return 'PROXY 192.168.31.107:8888';
//////         return 'PROXY 127.0.0.1:8888';
////         return 'PROXY 172.16.3.38:8888';
////        };
////      }
//    };

    //debug包打印日志
    if (BuildConfig.isDebug) {
      _dio.interceptors.add(LogInterceptor(
          request: false,
          requestBody: true,
          requestHeader: true,
          responseBody: true,
          responseHeader: false,
          error: true));
    }
    _dio.interceptors
        .add(InterceptorsWrapper(onError: onHttpError, onRequest: onRequest));
    _dio.interceptors.add(CookieManager(CookieJar()));
  }

  //处理请求
  onRequest(Options options) async {
    //拦截请求
//    _dio.interceptors.requestLock.lock();
    //处理请求头，获取本地SessionKey；
//    options.headers["Authorization"] ?? await LocalStorage.getSessionKey();
    //放行
//    _dio.interceptors.requestLock.unlock();
    return options;
  }

  //处理网络异常
  dynamic onHttpError(DioError e) {
    var code = e?.response?.statusCode;
    HttpError httpError;
    if (code == null) {
      if (e.message.startsWith("Connecting timeout") ||
          e.message.startsWith("Receiving data timeout")||
          e.message.startsWith("Connection refused")) {
        httpError = HttpError("网络不稳定，请求超时", "-1");
      } else {
        httpError = HttpError(e?.message, "-2");
      }
      return httpError;
    }
    switch (code) {
      case 404:
        httpError = HttpError("没有找到服务器", code.toString());
        break;
      case 302:
        httpError = HttpError("对象已临时移动", code.toString());
        break;
      default:
        httpError = HttpError("网络连接异常，请稍后再试", code.toString());
        break;
    }
    return httpError;
  }

  //网络请求
  Future<T> netFetch<T>(String path, params,
      {String method = Method.POST,
      Options option,
      String id,
      bool showToast = true,State state,String fromType}) async {
    Options options = option ?? Options();
    Response response;
    try {
      if(BuildConfig.isDebug)globalPrint('请求参数'+ params.toString());
      response = await _dio.request(path,
          data: method != Method.GET ? params : null,
          queryParameters: method == Method.GET ? params : null,
          options: options..method = method);
      if(state != null){
        globalPrint('===请求界面===' + state.runtimeType.toString());
      }
      globalPrint('===请求参数===' + params.toString());
      globalPrint('===请求地址===' + path.toString());
      globalPrint('===响应内容===' + response.data.toString());

      globalPrint('''
${state == null ? '' : '==========界面类型==========' + state.runtimeType.toString()}
${fromType == null ? '' : '==========类型$fromType=========='}
==========request==========' + ${params.toString()};
==========requestUrl==========' + ${path.toString()};
==========response==========' + ${response.toString()}
    ''');

    } on DioError catch (e) {
      if (showToast)
        Fluttertoast.showToast(msg: e?.error?.message, fontSize: 13.0);
      return Future.error(e.error);
    }
    Map res =
        (response.data is Map) ? response.data : json.decode(response.data);
    return EntityFactory.generateOBJ<T>(res);
//    String resCode = res['code']?.toString();
//    if (resCode == '0') {
//      return EntityFactory.generateOBJ<T>(res);
//    } else {
//      if (showToast)
//        Fluttertoast.showToast(msg: ApiCode.getMsg(resCode), fontSize: 13.0);
//      //处理返回数据错误
//      return Future.error(ResError(ApiCode.getMsg(resCode), resCode));
//    }
  }


  //上传图片
//  Future<T> upLoadImage<T>(String netpath,File image, {String key="file", bool showToast = true}) async {
//    String path = image.path;
//    var name = path.substring(path.lastIndexOf("/") + 1, path.length);
//    FormData formData = new FormData.from({
//      key: new UploadFileInfo(new File(path), name)
//    });
//    try {
//    var response = await _dio.post<String>(netpath, data: formData);
//    Map res =
//    (response.data is Map) ? response.data : json.decode(response.data);
//    String resCode = res['iRspCode']?.toString();
//    if (resCode == '0') {
//      return EntityFactory.generateOBJ<T>(res);
//    } else {
//      if (showToast)
//        Fluttertoast.showToast(msg: ApiCode.getMsg(resCode), fontSize: 13.0);
//      //处理返回数据错误
//      return Future.error(ResError(ApiCode.getMsg(resCode), resCode));
//    }
//    } on DioError catch (e) {
//      if (showToast)
//        Fluttertoast.showToast(msg: e?.error?.message, fontSize: 13.0);
//      return Future.error(e.error);
//    }
//  }
}

//请求异常
class HttpError implements Exception {
  String message;
  String statusCode;

  HttpError(this.message, this.statusCode);

  @override
  String toString() {
    return 'HttpError{message: $message, statusCode: $statusCode}';
  }
}

//接口数据异常
class ResError extends HttpError {
  ResError(String message, String statusCode) : super(message, statusCode);
}

/// 请求方法.
class Method {
  Method._();

  static const String GET = "GET";
  static const String POST = "POST";
  static const String PUT = "PUT";
  static const String HEAD = "HEAD";
  static const String DELETE = "DELETE";
  static const String PATCH = "PATCH";
}